/* /////////////////////////////////////////////////////////////////////////////
 * File:        TuppleFeature.d
 *
 * Purpose:     数字の組になってる（座標のある）特徴量
 *
 * Created      13th June 2007
 * Updated:     13th June 2007
 *
 * www:         http://
 *
 * Copyright (C) 2007 by Yasunobu Imamura
 *
 * This software is provided 'as-is', without any express or implied warranty.
 * In no event will the authors be held liable for any damages arising from the
 * use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not claim
 * that you wrote the original software. If you use this software in a product,
 * an acknowledgment in the product documentation would be appreciated but is
 * not required.
 *
 * 2. Altered source versions must be plainly marked as such, and must not be
 * misrepresented as being the original software.
 *
 * 3. This notice may not be removed or altered from any source distribution. 
 *
 * ////////////////////////////////////////////////////////////////////////// */

module gtree.TuppleFeature;

private import std.stdio;
private import std.math;
private import gtree.all;

class TuppleFeature(C, alias Norm, DT = C) : ISerializable, IMetrizable, ICloneable
{
	alias TuppleFeature!(C, Norm, DT) MyType;
	mixin Norm!(C, DT);

	C[] data;
	this()
	{
	}
	this(C[] data2)
	{
		data = data2.dup;
	}
	void serialize(Serializer s)
	{
		s.serialize(&data);
	}
	MyType clone()
	{
		return new MyType(data);
	}
}

template L_inftyNorm(C, DT)
{
	alias DT DistanceType;
	DistanceType distance(MyType o)
	{
		C[] a = this.data;
		C[] b = o.data;

		int len;
		if(b.length < a.length)
		{
			len = b.length;
		}
		else
		{
			len = a.length;
		}

		DistanceType d = 0;
		for(int i=0; i<len; ++i)
		{
			DistanceType d2;
			if(a[i] < b[i])
				d2 = b[i] - a[i];
			else
				d2 = a[i] - b[i];
			if(d<d2)
				d = d2;
		}
		return d;
	}
}

template L_1Norm(C, DT)
{
	alias DT DistanceType;
	DistanceType distance(MyType o)
	{
		C[] a = this.data;
		C[] b = o.data;

		int len;
		if(b.length < a.length)
		{
			len = b.length;
		}
		else
		{
			len = a.length;
		}

		DistanceType d = 0;
		for(int i=0; i<len; ++i)
		{
			if(a[i] < b[i])
				d += b[i] - a[i];
			else
				d += a[i] - b[i];
		}
		return d;
	}
}

template L_2Norm(C, DT)
{
	alias DT DistanceType;
	DistanceType distance(MyType o)
	{
		C[] a = this.data;
		C[] b = o.data;

		int len;
		if(b.length < a.length)
		{
			len = b.length;
		}
		else
		{
			len = a.length;
		}

		DistanceType d = 0;
		for(int i=0; i<len; ++i)
		{
			DistanceType kk = void;
			if(a[i] < b[i])
				kk = b[i] - a[i];
			else
				kk = a[i] - b[i];
			d += kk*kk;
		}
		return sqrt(d);
	}
}
